package server

import (
	"math/rand"
	"net"
	"src/zeus/common"
	"src/zeus/sess"
	"strconv"
	"time"

	"src/zeus/logger"

	"github.com/buguang01/util/flags"
	"github.com/spf13/viper"
)

// GetValidSrvPortInt 根据传入的最小端口和最大端口号，找一个可用端口，返回一个可用来绑定的地址
func GetValidSrvPortInt(minPort, maxPort int) int {
	if maxPort <= minPort {
		return minPort
	}
	maxRetry := 0
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for {
		port := r.Intn(maxPort-minPort) + minPort
		portStr := strconv.Itoa(port)

		l, err := net.Listen("tcp", ":"+portStr)
		if err != nil {
			logger.Error("尝试监听端口失败 errno: ", sess.GetErrno(err), " msg: ", err.Error())
			if maxRetry > 10 {
				break
			}
			maxRetry++
			time.Sleep(time.Second)
			continue
		} else {
			err = l.Close()
			if err != nil {
				logger.Error("关闭监听端口失败", err)
			}
			return port
		}
	}
	return 0
}

func GetValidSrvPort(minPort, maxPort int) string {
	port := GetValidSrvPortInt(minPort, maxPort)
	return strconv.Itoa(port)
}

// 获取NewServer需要的参数
func GetServerParm(vmap *viper.Viper) (srvID uint64, canConnectList, watchlist, oCanConnectList []uint8,
	innerlisten, inneraddr, outerlisten, outeraddr, httplisten, httpaddr string, fps int) {
	srvID = uint64(vmap.GetInt64("FlagId")) + uint64(flags.GetFlagByInt(common.ServerNumber))
	if inner := vmap.Get("Inner"); inner != nil {
		pmin := int(vmap.GetInt32("Inner.PortMin"))
		pmax := int(vmap.GetInt32("Inner.PortMax"))
		innerPort := GetValidSrvPort(pmin, pmax)
		Listen := vmap.GetString("Inner.Listen")
		Addr := vmap.GetString("Inner.Addr")
		innerlisten = Listen + ":" + innerPort
		inneraddr = Addr + ":" + innerPort
	} else {
		innerlisten = ""
		inneraddr = ""
	}
	if outer := vmap.Get("Outer"); outer != nil {
		pmin := int(vmap.GetInt32("Outer.PortMin"))
		pmax := int(vmap.GetInt32("Outer.PortMax"))
		innerPort := GetValidSrvPort(pmin, pmax)
		Listen := vmap.GetString("Outer.Listen")
		Addr := vmap.GetString("Outer.Addr")
		outerlisten = Listen + ":" + innerPort
		outeraddr = Addr + ":" + innerPort
	} else {
		outerlisten = ""
		outeraddr = ""
	}
	if htp := vmap.Get("Http"); htp != nil {
		pmin := int(vmap.GetInt32("Http.PortMin"))
		pmax := int(vmap.GetInt32("Http.PortMax"))
		innerPort := GetValidSrvPort(pmin, pmax)
		Listen := vmap.GetString("Http.Listen")
		Addr := vmap.GetString("Http.Addr")
		httplisten = Listen + ":" + innerPort
		httpaddr = Addr + ":" + innerPort
	} else {
		httplisten = ""
		httpaddr = ""
	}
	fps = int(vmap.GetInt32("FPS"))
	canConnectList = make([]uint8, 0, 10)
	stringList := vmap.GetIntSlice("LocalType")
	for _, v := range stringList {
		canConnectList = append(canConnectList, uint8(v))
	}
	watchlist = make([]uint8, 0, 10)
	stringList = vmap.GetIntSlice("WatchLocalTypes")
	for _, v := range stringList {
		watchlist = append(watchlist, uint8(v))
	}
	oCanConnectList = make([]uint8, 0, 10)
	stringList = vmap.GetIntSlice("GlobalType")
	for _, v := range stringList {
		oCanConnectList = append(canConnectList, uint8(v))
	}

	return
}
